package cn.stylefeng.guns.modular.api.controller;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLDecoder;
import java.security.PrivateKey;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;


import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAConfig;
import com.wechat.pay.java.core.cipher.RSASigner;
import com.wechat.pay.java.core.cipher.SignatureResult;
import com.wechat.pay.java.core.cipher.Signer;
import com.wechat.pay.java.core.util.IOUtil;
import com.wechat.pay.java.core.util.PemUtil;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.CloseOrderRequest;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse;
import com.wechat.pay.java.service.payments.jsapi.model.QueryOrderByOutTradeNoRequest;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.payments.model.Transaction.TradeStateEnum;

import org.springframework.core.io.ClassPathResource;

import cn.hutool.core.date.DateTime;
import cn.stylefeng.guns.GunsApplication;
import cn.stylefeng.guns.base.auth.context.LoginContextHolder;
import cn.stylefeng.guns.base.auth.service.AuthService;
import cn.stylefeng.guns.modular.api.tool.OrderCodeFactory;
import cn.stylefeng.guns.modular.api.tool.SignInfo;
import cn.stylefeng.guns.modular.api.tool.WxTool;
import cn.stylefeng.guns.modular.gui.entity.Banner;
import cn.stylefeng.guns.modular.gui.entity.Cangge;
import cn.stylefeng.guns.modular.gui.entity.Guifan;
import cn.stylefeng.guns.modular.gui.entity.Guige;
import cn.stylefeng.guns.modular.gui.entity.Myquan;
import cn.stylefeng.guns.modular.gui.entity.Order;
import cn.stylefeng.guns.modular.gui.entity.PTanchuang;
import cn.stylefeng.guns.modular.gui.entity.Quan;
import cn.stylefeng.guns.modular.gui.entity.Renyuan;
import cn.stylefeng.guns.modular.gui.entity.Shequ;
import cn.stylefeng.guns.modular.gui.entity.Tuihuan;
import cn.stylefeng.guns.modular.gui.entity.Tuwen;
import cn.stylefeng.guns.modular.gui.entity.Wp;
import cn.stylefeng.guns.modular.gui.entity.Yajin;
import cn.stylefeng.guns.modular.gui.entity.Yue;
import cn.stylefeng.guns.modular.gui.service.BannerService;
import cn.stylefeng.guns.modular.gui.service.CanggeService;
import cn.stylefeng.guns.modular.gui.service.GuifanService;
import cn.stylefeng.guns.modular.gui.service.GuigeService;
import cn.stylefeng.guns.modular.gui.service.MyquanService;
import cn.stylefeng.guns.modular.gui.service.OrderService;
import cn.stylefeng.guns.modular.gui.service.PTanchuangService;
import cn.stylefeng.guns.modular.gui.service.QuanService;
import cn.stylefeng.guns.modular.gui.service.RenyuanService;
import cn.stylefeng.guns.modular.gui.service.ShequService;
import cn.stylefeng.guns.modular.gui.service.TuihuanService;
import cn.stylefeng.guns.modular.gui.service.TuwenService;
import cn.stylefeng.guns.modular.gui.service.WpService;
import cn.stylefeng.guns.modular.gui.service.YajinService;
import cn.stylefeng.guns.modular.gui.service.YueService;
import cn.stylefeng.guns.sys.core.util.SaltUtil;
import cn.stylefeng.guns.sys.modular.consts.entity.SysConfig;
import cn.stylefeng.guns.sys.modular.consts.service.SysConfigService;
import cn.stylefeng.guns.sys.modular.system.entity.User;
import cn.stylefeng.guns.sys.modular.system.entity.UserInfo;
import cn.stylefeng.guns.sys.modular.system.factory.UserFactory;
import cn.stylefeng.guns.sys.modular.system.model.UserDto;
import cn.stylefeng.guns.sys.modular.system.service.UserInfoService;
import cn.stylefeng.guns.sys.modular.system.service.UserService;
import cn.stylefeng.roses.core.base.controller.BaseController;
import cn.stylefeng.roses.core.util.ToolUtil;
import cn.stylefeng.roses.kernel.model.response.ResponseData;
import cn.stylefeng.roses.kernel.model.response.SuccessResponseData;

@RestController
@RequestMapping("/wxapi")
public class ApiController extends BaseController {
	
	private static final String PrivateKey = "apiclient_key.pem";//密钥
	private static final String WeixinPayCert = "wechatpay_435D083ACC2E8C36DBE63204B1332CF4FBA9E7DE.pem";//微信支付证书
	private static final String mid = "1649207507";//商户ID
	private static final String SerialNumber = "4E8491726538D1EDEE5B0733CF993FAA5DEF0DAB";//证书序列号
	private static final String Appid = "wx62288580e267fca0";//APPID
	private static final String NotifyUrl = "https://p.cnyear.com/wxapi/notice";//通知回调URL
	@Autowired
	private UserInfoService userInfoService;
	@Autowired
	private UserService userService;
	@Autowired
	private AuthService authService;
	@Autowired
	private GuigeService guigeService;
	@Autowired
	private CanggeService canggeService;
	@Autowired
	private ShequService shequService;
	@Autowired
	private RenyuanService renyuanService;
	@Autowired
	private QuanService quanService;
	@Autowired
	private MyquanService myquanService;
	@Autowired
	private YueService yueService;
	@Autowired
	private WpService wpService;
	@Autowired
	private OrderService orderService;
	@Autowired
	private GuifanService guifanService;
	@Autowired
	private BannerService bannerService;
	@Autowired
	private SysConfigService sysConfigService;
	@Autowired
	private YajinService yajinService;
	@Autowired
	private TuihuanService tuihuanService;
	@Autowired
	private PTanchuangService tanchuangService;
	@Autowired
	private TuwenService tuwenService;
	
	
	/**
	 * 检查登录状态 如果已登录返回用户信息
	 * @return
	 */
	@RequestMapping(value = "/checklogin", method = RequestMethod.GET)
	public ResponseData checklogin() {

		if(LoginContextHolder.getContext().hasLogin()){
			return ResponseData.success(userInfoService.getOne(new QueryWrapper<UserInfo>().eq("user_id", LoginContextHolder.getContext().getUserId())));
		}else{
			return ResponseData.error("当前未登录");
		}
	}
	
	
	/**
     * 点击登录执行的动作
     *
     * @author Dong
     * @Date 2018/12/23 5:42 PM
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public ResponseData restLogin(@RequestParam("code") String code) {
    	
    	Map<String,Object> map = new HashMap<String, Object>();
    	
    	//获取OPENID
    	Map<String, String> infoMap = WxTool.getLoginInfo(code);
    	
    	String openid = infoMap.get("openid");
    	//String unionid = infoMap.get("unionid");
    	System.out.println(infoMap);
    	
    	//查询是否新用户
    	UserInfo ui = userInfoService.getOne(new QueryWrapper<UserInfo>()
    			.eq("uuid", openid));
    	
    	
    	if(ui==null) {//新增
    		
    		UserInfo newui = new UserInfo();
    		
    		UserDto user = new UserDto();
			user.setAccount(openid);
			user.setName("信游用户");
			user.setAvatar("https://res.uapps.cn/card/42d2a052-ab36-451d-b1e5-a7e1d1ba6362.png");
			user.setRoleId("5");
			user.setPassword("xinlianyun__++!!@.Wx");
			// 完善账号信息
	        String salt = SaltUtil.getRandomSalt();
	        String password = SaltUtil.md5Encrypt(user.getPassword(), salt);
	        User newUser = UserFactory.createUser(user, password, salt);
	        userService.save(newUser);
	        
	        
	        newui.setUserId(newUser.getUserId());
	        newui.setNickName("微信用户");
	        newui.setAvatar("https://res.uapps.cn/card/42d2a052-ab36-451d-b1e5-a7e1d1ba6362.png");
	        newui.setUuid(openid);
	        newui.setCreateTime(new DateTime());
	        
	        userInfoService.save(newui);
	        
	        ui = userInfoService.getOne(new QueryWrapper<UserInfo>().eq("uuid", openid));
    	}
    	
    	String token = authService.login(openid);
    	ui.setToken(token);

        return new SuccessResponseData(ui);
    }
	
    
    
    
    /**
     * 绑定手机号
     *
     * @author Dong
     * @Date 2018/12/23 5:42 PM
     */
    @RequestMapping("/bindPhone")
    public ResponseData bindPhone(@RequestParam("code") String code) {
    	
    	Long uid = LoginContextHolder.getContext().getUserId();
    	
    	//p判断是否有此用户
    	UserInfo ui = userInfoService.getOne(new QueryWrapper<UserInfo>()
    			.eq("user_id", uid));
    	
    	if(ui==null ) {
    		return ResponseData.error("绑定失败");
    	}
//    	if(ToolUtil.isNotEmpty(ui.getPhone())) {
//    		return ResponseData.error("禁止重复绑定");
//    	}
    	
    	UserInfo newui = ui;
    	
    	//获取微信手机号码
    	String phone = WxTool.getPhoneNum(code);
		if(ToolUtil.isEmpty(phone)) {
			return ResponseData.error("手机号获取失败");
		}
		
		newui.setPhone(phone);
		User u = userService.getById(uid);
		u.setPhone(phone);
		
		userInfoService.updateById(newui);
		userService.updateById(u);
		
        return ResponseData.success(newui);
    }
    
    
    
    /**
     * 获取规格列表
     *
     * @author Dong
     * @Date
     */
    @RequestMapping("/getGuige")
    public ResponseData getGuige() {
    	List<Guige> lg = guigeService.list(new QueryWrapper<Guige>()
    			.eq("del", 0));
        return ResponseData.success(lg);
    }
    
    
    /**
     * 获取客服手机号
     *
     * @author Dong
     * @Date
     */
    @RequestMapping("/getKfPhone")
    public ResponseData getKfPhone() {
    	SysConfig sc = sysConfigService.getOne(new QueryWrapper<SysConfig>()
        		.eq("code", "KFPHONE"));
        return ResponseData.success(sc.getValue());
    }
    
    
    /**
     * 获取小区列表
     *
     * @author Dong
     * @Date
     */
    @RequestMapping("/getShequ")
    public ResponseData getShequ(Long gid) {
    	List<Map<String,Object>> lm = shequService.listMaps(new QueryWrapper<Shequ>()
    			.last("WHERE FIND_IN_SET("+gid+",gids)"));
        return ResponseData.success(lm);
    }
    
    
    /**
     * 获取舱门
     *
     * @author Dong
     * @Date
     */
    @RequestMapping("/getCw")
    public ResponseData getCw(Long gid,Long sid) {
    	List<Map<String,Object>> lm = canggeService.listMaps(new QueryWrapper<Cangge>()
    			.eq("gid", gid));
    	
    	
    	for(int i=0;i<lm.size();i++) {
    		Object cid = lm.get(i).get("id");
    		
    		//判断生效中的订单，如果订单有，前端禁止选择
    		List<Order> lo = orderService.list(new QueryWrapper<Order>().eq("state", 1).eq("gid", gid).eq("sid", sid)
    				.last("AND FIND_IN_SET("+cid+",cgId)"));
    		if(lo.size()==0) {
    			lm.get(i).put("end", 0);
    		}else {
    			lm.get(i).put("end", 1);
    			
    			//判断更新 判断是否到期 到期就更改状态
    			Date date = new DateTime();
    			for(int ii=0;ii<lo.size();ii++) {
    				if(date.getTime()>lo.get(ii).getEndTime().getTime()) {
    					Order eo = lo.get(ii);
    					eo.setState(2);
    					orderService.updateById(eo);
    				}
    			}
    		}
    		
    		
    	}
    	
    	
        return ResponseData.success(lm);
    }
    
    
    /**
     * 添加人员
     *
     * @author Dong
     * @Date
     */
    @RequestMapping("/addRenyuan")
    public ResponseData addRenyuan(Renyuan ry) {
    	
    	List<Renyuan> lry = renyuanService.list(new QueryWrapper<Renyuan>().eq("del", 0).eq("uid", LoginContextHolder.getContext().getUserId()));
    	
    	//判断是否第一次添加，如果是 设为默认
    	if(lry.size()==0) {
    		ry.setDef(1);
    	}
    	
    	ry.setUid(LoginContextHolder.getContext().getUserId());
    	
    	renyuanService.save(ry);
    	
        return ResponseData.success();
    }
    
    
    /**
     * 获取人员
     *
     * @author Dong
     * @Date
     */
    @RequestMapping("/getRenyuan")
    public ResponseData getRenyuan() {
    	List<Renyuan> lry = renyuanService.list(new QueryWrapper<Renyuan>().select("id","def","name","INSERT(phone,4,4,'****') AS phone","INSERT(idCard,4,11,'***********') AS idCard").eq("del",0).eq("uid", LoginContextHolder.getContext().getUserId()).last("ORDER BY def DESC"));
        return ResponseData.success(lry);
    }
    
    
    /**
     * 切换默认人员
     *
     * @author Dong
     * @Date
     */
    @RequestMapping("/setDef")
    public ResponseData setDef(Long id) {
    	
    	Renyuan r = renyuanService.getById(id);
    	
    	//先更新所有 成非默认
    	renyuanService.update(new UpdateWrapper<Renyuan>().set("def", 0).eq("uid", LoginContextHolder.getContext().getUserId()));
    	
    	//再把当前设为默认
    	r.setDef(1);
    	renyuanService.updateById(r);
        return ResponseData.success();
    }
    
    
    /**
     * 获取默认人员
     *
     * @author Dong
     * @Date
     */
    @RequestMapping("/getDef")
    public ResponseData getDef() {
    	Renyuan r = renyuanService.getOne(new QueryWrapper<Renyuan>()
    			.select("id","def","name","INSERT(phone,4,4,'****') AS phone","INSERT(idCard,4,11,'***********') AS idCard")
    			.eq("uid", LoginContextHolder.getContext().getUserId())
    			.eq("def", 1)
    			.eq("del", 0));
        return ResponseData.success(r);
    }
    
    
    /**
     * 删除人员
     *
     * @author Dong
     * @Date
     */
    @RequestMapping("/delry")
    public ResponseData delry(Long id) {
    	
    	//软删除
    	
    	Renyuan r = renyuanService.getById(id);
    	r.setDel(1);
    	renyuanService.updateById(r);
        return ResponseData.success();
    }
    
    
    /**
     * 获取人员信息
     *
     * @author Dong
     * @Date
     */
    @RequestMapping("/getrybyid")
    public ResponseData getrybyid(Long id) {
    	Renyuan r = renyuanService.getById(id);
        return ResponseData.success(r);
    }
    
    
    /**
     * 获取人员信息
     *
     * @author Dong
     * @Date
     */
    @RequestMapping("/updry")
    public ResponseData updry(Long id,String name,String idCard,String phone) {
    	Renyuan r = renyuanService.getById(id);
    	r.setName(name);
    	r.setIdCard(idCard);
    	r.setPhone(phone);
    	renyuanService.updateById(r);
        return ResponseData.success();
    }
    
    
    /**
     * 获取优惠券列表
     *
     * @author Dong
     * @Date
     */
    @RequestMapping("/getquan")
    public ResponseData getquan() {
    	Long uid = LoginContextHolder.getContext().getUserId();
    	List<Map<String,Object>> lm = quanService.listMaps();
    	
    	//遍历 查询优惠券领用状态
    	
    	for(int i=0;i<lm.size();i++) {
    		
    		Integer state = 99;//99 可领取 0已领取未使用  1 已使用 2已过期
    		
    		String msg = "";
    		
    		Long qid = (Long) lm.get(i).get("id");
    		
    		//获取我已领取的券
    		Myquan mq = myquanService.getOne(new QueryWrapper<Myquan>()
    				.eq("uid", uid).eq("qid", qid));
    		
    		if(ToolUtil.isEmpty(mq)) {//未领取 可领
    			state = 99;
    		}else {
    			
    			//已领取，查询是否到期 只更新未使用的 状态是0的
    			
    			Date lqrq = mq.getLqtime();
        		Integer yxq = mq.getYxq();
        		Date now = new DateTime();
        		Date end = getDateAfterNdays(lqrq,yxq);
        		
        		//过期更新
        		if(now.getTime() > end.getTime()&&mq.getState()==0) {
        			mq.setState(2);
        			myquanService.updateById(mq);
        		}
        		
        		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        		
        		msg = dateFormat.format(end)+"过期";
    			state = mq.getState();
    		}
    		
    		lm.get(i).put("state", state);
    		lm.get(i).put("msg", msg);
    		
    	}
    	
        return ResponseData.success(lm);
    }
    
    
    /**
     * 领券
     *
     * @author Dong
     * @Date
     */
    @RequestMapping("/lingquan")
    public ResponseData lingquan(Long qid) {
    	Long uid = LoginContextHolder.getContext().getUserId();
    	
    	List<Myquan> lm = myquanService.list(new QueryWrapper<Myquan>()
    			.eq("uid", uid).eq("qid", qid));
    	
    	if(lm.size()!=0) {
    		return ResponseData.error("请勿重复领取");
    	}
    	
    	
    	Quan q = quanService.getById(qid);
    	
    	Integer all = myquanService.count(new QueryWrapper<Myquan>()
    			.eq("qid", qid));
    	
    	if(all<q.getNum()) {
    		Myquan mq = new Myquan();
        	
        	mq.setYxq(q.getYxq());
        	mq.setLqtime(new DateTime());
        	mq.setQid(qid);
        	mq.setUid(uid);
        	mq.setState(0);
        	
        	myquanService.save(mq);
            return ResponseData.success("领取成功");
    	}else {
    		return ResponseData.error("领取失败，数量不足");
    	}
    	
    	
    }
    
    
    
    /**
     * 获取我的优惠券
     *
     * @author Dong
     * @Date
     */
    @RequestMapping("/getmyquan")
    public ResponseData getmyquan() {
    	Long uid = LoginContextHolder.getContext().getUserId();
    	List<Map<String,Object>> lm = myquanService.listMaps(new QueryWrapper<Myquan>()
    			.eq("uid", uid).eq("state", 0));
    	
    	if(lm.size()==0) {
    		return ResponseData.success(lm);
    	}
    	
    	//去掉已过期的券 并更新
    	for(int i=0;i<lm.size();i++) {
    		
    		Myquan mq = myquanService.getById((Long) lm.get(i).get("id"));
    		
    		Long qid = (Long) lm.get(i).get("qid");
    		Quan q = quanService.getById(qid);
    		
    		Date lqrq = (Date) lm.get(i).get("lqtime");
    		Integer yxq = (Integer) lm.get(i).get("yxq");
    		Date now = new DateTime();
    		Date end = getDateAfterNdays(lqrq,yxq);
    		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    		
    		lm.get(i).put("msg",dateFormat.format(end)+"过期");
    		lm.get(i).put("zk",q.getZk());
    		//过期更新
    		if(now.getTime() > end.getTime()) {
    			lm.get(i).put("state",2);
    			mq.setState(2);
    			myquanService.updateById(mq);
    			lm.remove(i);
    		}
    	}
    	
        return ResponseData.success(lm);
    }
    
    
    /**
     * 获取月数
     * @return
     */
    @RequestMapping("/getyue")
    public ResponseData getyue() {
    	List<Yue> ly = yueService.list();
    	return ResponseData.success(ly);
    }
    
    /**
     * 获取物品类别
     * @return
     */
    @RequestMapping("/getwp")
    public ResponseData getwp() {
    	List<Wp> lw = wpService.list();
    	return ResponseData.success(lw);
    }
    
    /**
     * 更新订单状态  支付成功后
     * @return
     */
    @RequestMapping("/updateOrder")
    public ResponseData updateOrder(String order) throws IOException, ParseException {
    	
    	
    	ClassPathResource resourcePrivateKey = new ClassPathResource(PrivateKey);
    	ClassPathResource resourceWeixinPayCert = new ClassPathResource(WeixinPayCert);
    	String privateKeyFromPath = resourcePrivateKey.getFile().getPath();
    	String wechatPayCertificatesFromPath = resourceWeixinPayCert.getFile().getPath();
    	
    	Config config = new RSAConfig.Builder()
    			.merchantId(mid)//商户ID
    			.privateKeyFromPath(privateKeyFromPath)//商户私钥文件(apiclient_key.pem)路径
    			.merchantSerialNumber(SerialNumber)//商户证书序列号 例如-证书序列号：54776TTTF8F77EXXX3641FAB5F940FII11C65347
    			.wechatPayCertificatesFromPath(wechatPayCertificatesFromPath)//微信支付平台证书文件路径 例如：wechatpay_3A4AF69999DF01F39BB08C21C1C29B6AA17C074N.pem
    			.build();
    	
    	JsapiService service = new JsapiService.Builder().config(config).build();
    	
    	
    	Order o = orderService.getOne(new QueryWrapper<Order>().eq("orderNum", order));
    	
    	QueryOrderByOutTradeNoRequest qt = new QueryOrderByOutTradeNoRequest();
    	qt.setMchid(mid);
    	qt.setOutTradeNo(order);
    	
    	
    	Transaction response = service.queryOrderByOutTradeNo(qt);
    	
    	System.out.println(response);
    	System.out.println(response.getTradeState());
    	
    	if(TradeStateEnum.SUCCESS.equals(response.getTradeState())) {
    		
    		String tm = response.getSuccessTime();
    		
    		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
    		Date newTime = format.parse(tm);
    		
    		o.setPayTime(newTime);
        	o.setState(1);
        	o.setPaystate(1);
        	orderService.updateById(o);
        	o.setWp(null);
        	
        	//更新券状态
        	if(ToolUtil.isNotEmpty(o.getQid())) {
        		Myquan mq = myquanService.getById(o.getQid());
        		mq.setState(1);
        		myquanService.updateById(mq);
        	}
        	
        	
        	
        	return ResponseData.success(o);
    	}else {
    		return ResponseData.error("订单错误");
    	}
    	
    	
    }
    
    
    /**
     * 检查优惠券是否可用
     * @param id
     * @return
     */
    @RequestMapping("/checkquan")
    public ResponseData checkquan(Long id) {
    	
    	Myquan mq = myquanService.getById(id);
    	
    	Date lqrq = mq.getLqtime();
		Integer yxq = mq.getYxq();
		Date now = new DateTime();
		Date end = getDateAfterNdays(lqrq,yxq);
		
		if(mq.getState()==0) {
			if(now.getTime()>end.getTime()) {
				mq.setState(2);
				myquanService.updateById(mq);
				return ResponseData.error("");
			}else {
				return ResponseData.success("");
			}
		}else {
			return ResponseData.error("");
		}
    }
    
    /**
     * 创建邓丹
     * @param info 储物柜信息
     * @param quan 优惠券信息
     * @param user 联系人信息
     * @param wp 物品信息
     * @param yue 储存时长
     * @param start 开始时间
     * @param other其他物品
     * @param gid 所属规格
     * @param sid 所属小区
     * @return
     * @throws IOException
     */
    @RequestMapping("/createOrder")
    public ResponseData createOrder(String info,String quan,String user,String wp,Integer yue,Date start,String other,Long gid,Long sid) throws IOException {
    	
    	Long uid = LoginContextHolder.getContext().getUserId();
		
		List<Yajin> ly = yajinService.list(new QueryWrapper<Yajin>()
				.eq("state", 1).eq("uid", uid));
		
		if(ly.size()==0) {
			return ResponseData.error(101,"未缴纳押金");
		}
    	
    	
    	
    	JSONObject infojson = DeCodeAndRecJson(info);
    	JSONObject quanjson = DeCodeAndRecJson(quan);
    	JSONObject userjson = DeCodeAndRecJson(user);
    	
    	BigDecimal je = new BigDecimal("0");
    	
    	
    	JSONArray cw = infojson.getJSONArray("cw");
    	
    	List<Long> cids = new ArrayList<Long>();
    	List<String> names = new ArrayList<String>();
    	
    	//计算价格
    	for(int i=0;i<cw.size();i++) {
    		JSONObject item = cw.getJSONObject(i);
    		je = je.add(item.getBigDecimal("jiage"));
    		cids.add(item.getLong("id"));
    		names.add(item.getString("num"));
    	}
    	
    	Order order =new Order();
    	
    	order.setGid(gid);
    	order.setSid(sid);
    	
    	//计算价格 乘以月数
    	BigDecimal allje = je.multiply(new BigDecimal(yue));
    	order.setYuanjia(allje.setScale(2,BigDecimal.ROUND_DOWN));
    	
    	Calendar cal = Calendar.getInstance();
    	
    	cal.setTime(start);
    	cal.add(Calendar.MONTH, yue);
    	
    	order.setStarTime(start);
    	
    	order.setEndTime(cal.getTime());
    	
    	order.setHowlong(yue);
    	order.setCgId(StringUtils.join(cids, ","));
    	order.setCgStr(StringUtils.join(names, ","));
    	order.setWp(wp);
    	
    	Renyuan ry = renyuanService.getById(userjson.getLong("id"));
    	order.setPhone(ry.getPhone());
    	order.setUsername(ry.getName());
    	order.setIdCard(ry.getIdCard());
    	
    	
    	//计算价格 判断是否使用优惠券
    	if(quanjson!=null) {
    		order.setQid(quanjson.getLong("id"));
    		BigDecimal lv = quanjson.getBigDecimal("zk");
    		lv = lv.divide(new BigDecimal(10));//折扣
    		order.setYhje(allje.multiply(lv).setScale(2,BigDecimal.ROUND_DOWN));
    		order.setShifu(order.getYhje().setScale(2,BigDecimal.ROUND_DOWN));
    	}else {
    		order.setShifu(allje.setScale(2,BigDecimal.ROUND_DOWN));
    	}
    	
    	order.setState(0);
    	order.setCreateTime(new DateTime());
    	order.setUid(LoginContextHolder.getContext().getUserId());
    	order.setOrderNum(OrderCodeFactory.getOrderCode());
    	
    	
    	order.setPaystate(0);
    	
    	Map<String,Object> resmap = new HashMap<String, Object>();
    	
    	SignInfo resinfo = CreateWxOrder(order);
    	
    	resmap.put("appId", resinfo.getAppId());
    	resmap.put("timeStamp", resinfo.getTimeStamp());
    	resmap.put("nonceStr", resinfo.getNonceStr());
    	resmap.put("packageStr", resinfo.getPackageStr());
    	resmap.put("signType", resinfo.getSignType());
    	resmap.put("paySign", resinfo.getPaySign());
    	
    	
    	resmap.put("order", order.getOrderNum());
    	
    	
    	System.out.println(order);
    	
    	return ResponseData.success(resmap);
    }
    
    
    
    
    private SignInfo CreateWxOrder(Order order) throws IOException {
    	
    	ClassPathResource resourcePrivateKey = new ClassPathResource(PrivateKey);
    	ClassPathResource resourceWeixinPayCert = new ClassPathResource(WeixinPayCert);
    	String privateKeyFromPath = resourcePrivateKey.getFile().getPath();
    	String wechatPayCertificatesFromPath = resourceWeixinPayCert.getFile().getPath();
    	
    	Config config = new RSAConfig.Builder()
    			.merchantId(mid)//商户ID
    			.privateKeyFromPath(privateKeyFromPath)//商户私钥文件(apiclient_key.pem)路径
    			.merchantSerialNumber(SerialNumber)//商户证书序列号 例如-证书序列号：54776TTTF8F77EXXX3641FAB5F940FII11C65347
    			.wechatPayCertificatesFromPath(wechatPayCertificatesFromPath)//微信支付平台证书文件路径 例如：wechatpay_3A4AF69999DF01F39BB08C21C1C29B6AA17C074N.pem
    			.build();
    	
    	JsapiService service = new JsapiService.Builder().config(config).build();
    	PrepayRequest request = new PrepayRequest();
    	
    	BigDecimal fen = order.getShifu().multiply(new BigDecimal(100));
    	
    	Amount amount = new Amount();
    	amount.setTotal(fen.intValue());
        request.setAmount(amount);
        request.setAppid(Appid);
        request.setMchid(mid);
        request.setDescription("储存服务购买-"+order.getHowlong()+"月");
        request.setNotifyUrl(NotifyUrl);
        request.setOutTradeNo(order.getOrderNum());
        Payer payer = new Payer();
        
        UserInfo ui = userInfoService.getOne(new QueryWrapper<UserInfo>().eq("user_id", order.getUid()));
        
        payer.setOpenid(ui.getUuid());
        request.setPayer(payer);
        
        PrepayResponse response = service.prepay(request);
        
        SignInfo info = generateWeixinSigner(response.getPrepayId(),privateKeyFromPath);
        
        if(ToolUtil.isNotEmpty(info.getPaySign())) {
        	order.setNonceStr(info.getNonceStr());
        	order.setPackages(info.getPackageStr());
        	order.setPaySign(info.getPaySign());
        	order.setTimeStamp(info.getTimeStamp());
        	order.setSignType(info.getSignType());
        	orderService.save(order);
        }
        
		return info;
	}
    
    
    @PostMapping(value = "/notice")
    public Map<String, String> callBack(@RequestBody JSONObject jsonObject) {
        String method = Thread.currentThread().getStackTrace()[1].getMethodName();
 
        //解密校验
 
        Map<String, String> res = new HashMap<>();
        res.put("code", "SUCCESS");
        res.put("message", "成功");
        return res;
    }
    
    
    
  //注意 SignInfo 是我自己定义的一个实体类，你们也可以自己定义一个
    public SignInfo generateWeixinSigner(String prepayid,String privateKeyFromPath){
      String privateKeyStr = null;
      try {
          //privateKeyFromPath 是私钥文件(apiclient_key.pem)路径
          //apiclient_key.pem 这个文件路径在你的后台代码里动态获取
          privateKeyStr = IOUtil.loadStringFromPath(privateKeyFromPath);
      } catch (IOException e) {
          e.printStackTrace();
      }
      PrivateKey key = PemUtil.loadPrivateKeyFromString(privateKeyStr);
     
      //拿到 预支付ID（prepayid）值 
      //假如-预支付ID：prepayid = "woLD34lk34lk345l345jl345j3l4534ok"
      //假如-小程序ID：appid= "applasdiasdfljsf"
      //假如-证书序列号：weixinMerchantSerialNumber = "ASDF98SDFAS9D8FASD9F8SAFAS9DF8ASDF98ASDF9S8F98"
      String packageStr = String.format("prepay_id=%s", prepayid);
      SignInfo info = new SignInfo();
      info.setAppId(Appid);
      info.setTimeStamp("" + System.currentTimeMillis());
      info.setNonceStr(generateOrderNumber(30));
      info.setPackageStr(packageStr);
      String str = info.toString();
     
      Signer rsaSigner = new RSASigner(SerialNumber, key);
      SignatureResult signatureResult = rsaSigner.sign(str);
      info.setPaySign(signatureResult.getSign());
      return info;
    }
    
    public static String generateOrderNumber(int size) {
    	  String abc = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890";
    	  //指定长度size = 30
    	  //指定取值范围 abc 如果不指定取值范围，中文环境下会乱码
    	  String str = RandomStringUtils.random(size, abc);
    	  return str;
   }


	private JSONArray DeCodeAndRecJsonArr(String wp) {
    	JSONArray jsonarr = JSONArray.parseArray(URLDecoder.decode(wp));
		return jsonarr;
	}


	@SuppressWarnings("deprecation")
	private JSONObject DeCodeAndRecJson(String info) {
    	
    	JSONObject json = JSONObject.parseObject(URLDecoder.decode(info));
    	
		return json;
	}
	
	
	
	@RequestMapping("/getmyorder")
    public ResponseData getwp(String type) {
		
		//更新状态
		
		List<Order> lo = orderService.list(new QueryWrapper<Order>().eq("state", 1).eq("uid", LoginContextHolder.getContext().getUserId()));
		
		updateOrderState(lo);
		
		List<Map<String,Object>> lm = new ArrayList<Map<String,Object>>();
		
		if("all".equals(type)) {
			lm = orderService.listMaps(new QueryWrapper<Order>()
					.eq("uid", LoginContextHolder.getContext().getUserId()));
		}
		
		if("used".equals(type)) {
			lm = orderService.listMaps(new QueryWrapper<Order>()
					.eq("uid", LoginContextHolder.getContext().getUserId())
					.eq("state", 1));
		}
		
		if("nopay".equals(type)) {
			lm = orderService.listMaps(new QueryWrapper<Order>()
					.eq("uid", LoginContextHolder.getContext().getUserId())
					.eq("state", 0)
					.eq("paystate", 0));
		}
		
		
		
    	return ResponseData.success(lm);
    }
	
	
	
	
	@RequestMapping("/getmyordernum")
    public ResponseData getmyordernum() {
		
		//更新状态
		
		List<Order> lo = orderService.list(new QueryWrapper<Order>().eq("state", 1).eq("uid", LoginContextHolder.getContext().getUserId()));
		
		updateOrderState(lo);
		
		Integer all = 0;
		Integer used = 0;
		Integer nopay = 0;
		
		Map<String,Object> map = new HashMap<String, Object>();
		
		all = orderService.count(new QueryWrapper<Order>()
				.eq("uid", LoginContextHolder.getContext().getUserId()));
		
		used = orderService.count(new QueryWrapper<Order>()
				.eq("uid", LoginContextHolder.getContext().getUserId())
				.eq("state", 1));
		
		nopay = orderService.count(new QueryWrapper<Order>()
				.eq("uid", LoginContextHolder.getContext().getUserId())
				.eq("state", 0)
				.eq("paystate", 0));
		
		map.put("all", all);
		map.put("used", used);
		map.put("nopay", nopay);
		
    	return ResponseData.success(map);
    }
	
	
	
	@SuppressWarnings("deprecation")
	@RequestMapping("/getorderbyid")
    public ResponseData getorderbyid(Long id) {
		
		Map<String,Object> order = orderService.getMap(new QueryWrapper<Order>()
				.eq("uid", LoginContextHolder.getContext().getUserId())
				.eq("id", id));
		
		Shequ sq = shequService.getById(Long.valueOf(order.get("sid").toString()));
		
		order.put("shequ", sq);
		
		String wp = order.get("wp").toString();
		
		wp = URLDecoder.decode(wp);
		
		System.out.println(wp);
		
		System.out.println(JSON.toJSONString(sq));
		
		JSONArray json = DeCodeAndRecJsonArr(wp);
		order.put("wplist", json);
		
		if(order.containsKey("qid")) {
			if(ToolUtil.isNotEmpty(order.get("qid"))) {
				Quan quan = quanService.getById(Long.valueOf(order.get("qid").toString()));
				order.put("quan", quan);
			}
		}
		
    	return ResponseData.success(order);
    }
	
	@RequestMapping("/getguifan")
	public ResponseData getguifan() {
		List<Guifan> lg = guifanService.list();
		return ResponseData.success(lg);
	}
	
	
	@RequestMapping("/gebanner")
	public ResponseData gebanner(Integer type) {
		List<Banner> lb = bannerService.list(new QueryWrapper<Banner>()
				.eq("type", type));
		return ResponseData.success(lb);
	}
	
	
	/**
	 * 获取押金缴纳状态
	 * @return
	 */
	@RequestMapping("/getYjState")
	public ResponseData getYjState() {
		Long uid = LoginContextHolder.getContext().getUserId();
		
		List<Yajin> ly = yajinService.list(new QueryWrapper<Yajin>()
				.eq("state", 1).eq("uid", uid));
		
		if(ly.size()==0) {
			return ResponseData.error("未缴纳");
		}else {
			return ResponseData.success(ly.get(0));
		}
	}
	
	
	/**
	 * 缴纳押金
	 * @return
	 * @throws IOException 
	 */
	@RequestMapping("/payYajin")
	public ResponseData payYajin() throws IOException {
		
		
		Long uid = LoginContextHolder.getContext().getUserId();
		
		List<Yajin> ly = yajinService.list(new QueryWrapper<Yajin>()
				.eq("state", 1).eq("uid", uid));
		
		if(ly.size()>0) {
			return ResponseData.error("请勿重复缴纳");
		}
		
		SysConfig sc = sysConfigService.getOne(new QueryWrapper<SysConfig>()
        		.eq("code", "YJNUM"));
		
		Yajin yj = new Yajin();
		yj.setOutTradeNo(OrderCodeFactory.getOrderCode());
		yj.setYajin(new BigDecimal(sc.getValue()));
		yj.setUid(LoginContextHolder.getContext().getUserId());
		yj.setState(0);
		
		
		Map<String,Object> resmap = new HashMap<String, Object>();
    	
    	SignInfo resinfo = CreateYjOrder(yj);
    	
    	resmap.put("appId", resinfo.getAppId());
    	resmap.put("timeStamp", resinfo.getTimeStamp());
    	resmap.put("nonceStr", resinfo.getNonceStr());
    	resmap.put("packageStr", resinfo.getPackageStr());
    	resmap.put("signType", resinfo.getSignType());
    	resmap.put("paySign", resinfo.getPaySign());
    	resmap.put("order", yj.getOutTradeNo());
		return ResponseData.success(resmap);
	}


	private SignInfo CreateYjOrder(Yajin yj) throws IOException {
		ClassPathResource resourcePrivateKey = new ClassPathResource(PrivateKey);
    	ClassPathResource resourceWeixinPayCert = new ClassPathResource(WeixinPayCert);
    	String privateKeyFromPath = resourcePrivateKey.getFile().getPath();
    	String wechatPayCertificatesFromPath = resourceWeixinPayCert.getFile().getPath();
    	
    	Config config = new RSAConfig.Builder()
    			.merchantId(mid)//商户ID
    			.privateKeyFromPath(privateKeyFromPath)//商户私钥文件(apiclient_key.pem)路径
    			.merchantSerialNumber(SerialNumber)//商户证书序列号 例如-证书序列号：54776TTTF8F77EXXX3641FAB5F940FII11C65347
    			.wechatPayCertificatesFromPath(wechatPayCertificatesFromPath)//微信支付平台证书文件路径 例如：wechatpay_3A4AF69999DF01F39BB08C21C1C29B6AA17C074N.pem
    			.build();
    	
    	JsapiService service = new JsapiService.Builder().config(config).build();
    	PrepayRequest request = new PrepayRequest();
    	
    	BigDecimal fen = yj.getYajin().multiply(new BigDecimal(100));
    	
    	Amount amount = new Amount();
    	amount.setTotal(fen.intValue());
        request.setAmount(amount);
        request.setAppid(Appid);
        request.setMchid(mid);
        request.setDescription("舱鼠空间押金缴纳");
        request.setNotifyUrl(NotifyUrl);
        request.setOutTradeNo(yj.getOutTradeNo());
        Payer payer = new Payer();
        
        UserInfo ui = userInfoService.getOne(new QueryWrapper<UserInfo>().eq("user_id", yj.getUid()));
        
        payer.setOpenid(ui.getUuid());
        request.setPayer(payer);
        
        PrepayResponse response = service.prepay(request);
        
        SignInfo info = generateWeixinSigner(response.getPrepayId(),privateKeyFromPath);
        
        if(ToolUtil.isNotEmpty(info.getPaySign())) {
        	yajinService.save(yj);
        }
        
		return info;
	}
	
	
	
	/**
     * 更新订单状态  支付成功后
     * @return
     */
    @RequestMapping("/updateYjOrder")
    public ResponseData updateYjOrder(String order) throws IOException, ParseException {
    	
    	
    	ClassPathResource resourcePrivateKey = new ClassPathResource(PrivateKey);
    	ClassPathResource resourceWeixinPayCert = new ClassPathResource(WeixinPayCert);
    	String privateKeyFromPath = resourcePrivateKey.getFile().getPath();
    	String wechatPayCertificatesFromPath = resourceWeixinPayCert.getFile().getPath();
    	
    	Config config = new RSAConfig.Builder()
    			.merchantId(mid)//商户ID
    			.privateKeyFromPath(privateKeyFromPath)//商户私钥文件(apiclient_key.pem)路径
    			.merchantSerialNumber(SerialNumber)//商户证书序列号 例如-证书序列号：54776TTTF8F77EXXX3641FAB5F940FII11C65347
    			.wechatPayCertificatesFromPath(wechatPayCertificatesFromPath)//微信支付平台证书文件路径 例如：wechatpay_3A4AF69999DF01F39BB08C21C1C29B6AA17C074N.pem
    			.build();
    	
    	JsapiService service = new JsapiService.Builder().config(config).build();
    	
    	
    	Yajin o = yajinService.getOne(new QueryWrapper<Yajin>().eq("outTradeNo", order));
    	
    	QueryOrderByOutTradeNoRequest qt = new QueryOrderByOutTradeNoRequest();
    	qt.setMchid(mid);
    	qt.setOutTradeNo(order);
    	
    	
    	Transaction response = service.queryOrderByOutTradeNo(qt);
    	
    	System.out.println(response);
    	System.out.println(response.getTradeState());
    	
    	if(TradeStateEnum.SUCCESS.equals(response.getTradeState())) {
    		
    		String tm = response.getSuccessTime();
    		
    		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
    		Date newTime = format.parse(tm);
    		
    		o.setJnrq(newTime);
        	o.setState(1);
        	o.setTransactionId(response.getTransactionId());
        	yajinService.updateById(o);
        	return ResponseData.success(o);
    	}else {
    		return ResponseData.error("订单错误");
    	}
	
    }
    
    
    
    /**
     * 失败后取消押金订单
     * @return
     */
    @RequestMapping("/delYjOrder")
    public ResponseData delYjOrder(String order) throws IOException, ParseException {
    	
    	
    	ClassPathResource resourcePrivateKey = new ClassPathResource(PrivateKey);
    	ClassPathResource resourceWeixinPayCert = new ClassPathResource(WeixinPayCert);
    	String privateKeyFromPath = resourcePrivateKey.getFile().getPath();
    	String wechatPayCertificatesFromPath = resourceWeixinPayCert.getFile().getPath();
    	
    	Config config = new RSAConfig.Builder()
    			.merchantId(mid)//商户ID
    			.privateKeyFromPath(privateKeyFromPath)//商户私钥文件(apiclient_key.pem)路径
    			.merchantSerialNumber(SerialNumber)//商户证书序列号 例如-证书序列号：54776TTTF8F77EXXX3641FAB5F940FII11C65347
    			.wechatPayCertificatesFromPath(wechatPayCertificatesFromPath)//微信支付平台证书文件路径 例如：wechatpay_3A4AF69999DF01F39BB08C21C1C29B6AA17C074N.pem
    			.build();
    	
    	JsapiService service = new JsapiService.Builder().config(config).build();
    	
    	
    	Yajin o = yajinService.getOne(new QueryWrapper<Yajin>().eq("outTradeNo", order));
    	
    	
    	CloseOrderRequest cor = new CloseOrderRequest();
    	cor.setMchid(mid);
    	cor.setOutTradeNo(o.getOutTradeNo());
    	service.closeOrder(cor);
    	
    	yajinService.removeById(o.getId());
    	
    	return ResponseData.success(o);
    }
    
    
    
    
    /**
     * 失败后取消押金订单
     * @return
     */
    @RequestMapping("/thsq")
    public ResponseData thsq() throws IOException, ParseException {
    	Long uid = LoginContextHolder.getContext().getUserId();
    	
    	List<Yajin> lyj = yajinService.list(new QueryWrapper<Yajin>()
    			.eq("state", 1).eq("uid", uid));
    	
    	if(lyj.size()==0) {
			return ResponseData.error("未缴纳押金");
		}
    	
    	//判断是否有进行中的订单
    	
    	List<Order> lo = orderService.list(new QueryWrapper<Order>()
    			.eq("uid", uid)
    			.eq("state", 1)
    			.eq("paystate", 1)
    			.lt("endTime", new DateTime()));
    	
    	if(lo.size()!=0) {
    		return ResponseData.error(101, "有订单未到期");
    	}
    	
    	
    	
    	
    	Yajin yj = lyj.get(0);
    	
    	Tuihuan th = new Tuihuan();
    	th.setOrderId(yj.getOutTradeNo());
    	th.setUid(uid);
    	th.setState(0);
    	tuihuanService.save(th);
    	
    	return ResponseData.success();
    }
    
    
    
    /**
     * 失败后取消押金订单
     * @return
     */
    @RequestMapping("/gettc")
    public ResponseData gettc(){
    	PTanchuang pt = tanchuangService.getById(1);
    	return ResponseData.success(pt);
    }
	
	
    
    
    /**
     * 获取图文
     * @return
     */
    @RequestMapping("/gettuwen")
    public ResponseData gettuwen(Long id){
    	
    	Tuwen tw = tuwenService.getById(id);
    	
    	return ResponseData.success(tw);
    }
    
    /**
     * 获取图文
     * @return
     */
    @RequestMapping("/gettuwenlist")
    public ResponseData gettuwenlist(){
    	List<Tuwen> tws = tuwenService.list();
    	return ResponseData.success(tws);
    }
    
    
	
	
	
	
	


	private void updateOrderState(List<Order> lo) {
		for(int i=0;i<lo.size();i++) {
			Order o = lo.get(i);
			Date date = new DateTime();
			if(date.getTime()>o.getEndTime().getTime()) {
				o.setState(2);
				orderService.updateById(o);
			}
		}
	}


	public Date getDateAfterNdays(Date lqrq,int days){
		  Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"));
		  calendar.setTimeInMillis(lqrq.getTime()+1000L * 60 * 60 * 24 * days);
		  return calendar.getTime();   
	}
    
}